package src.G_E_AnnotationAndReflection;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

// 使用反射获取类信息（属性和方法）
public class G02_ReflectionTest04_1 {
    public static void main(String[] args) throws Exception {
        // 1、创建people类的实例
        Class c = People.class; // 获取Class对象
        People p1 = (People) c.newInstance(); // 构造一个people对象
        System.out.println(p1); // people{name='null', age=0}
        // 获得类的名字
        System.out.println(c.getName()); // 获得包名+类型  src.G_E_AnnotationAndReflection.People
        System.out.println(c.getSimpleName()); // 获得类名  People

        // 2、调用属性
        Field ageField = c.getField("age");
        ageField.set(p1,10);
        System.out.println(ageField.get(p1)); // 10
        // 获得所有属性（私有的获取不到）
        for (Field field : c.getFields()) {
            System.out.println(field); // public int src.G_E_AnnotationAndReflection.People.age
        }
        // 获取全部属性
        for (Field field : c.getDeclaredFields()) {
            System.out.println(field);
            // private java.lang.String src.G_E_AnnotationAndReflection.People.name
            // public int src.G_E_AnnotationAndReflection.People.age
        }

        // 3、调用show()
        Method showMethod = c.getMethod("show");
        showMethod.invoke(p1);
        // 获取类的方法(本类和父类)，这里是People类和Object类
        for (Method method : c.getMethods()) {
            System.out.println(method);
        }
        // 获取类的方法(本类)，People类的所有方法 toString()，show()，showNation(java.lang.String)
        for (Method method : c.getDeclaredMethods()) {
            System.out.println(method);
        }

        // 获取类的构造器
        for (Constructor constructor : c.getConstructors()) {
            System.out.println("getConstructors:"+ constructor); // 获得public修饰的
        }
        for (Constructor constructor : c.getDeclaredConstructors()) {
            System.out.println("getDeclaredConstructors:"+constructor); // 获得全部
        }

        System.out.println("=======================");

        // 4、调用私有的构造器，创建People实例
        Constructor cons = c.getDeclaredConstructor(String.class,int.class);
        cons.setAccessible(true); // 设置私有结构允许访问，是启动和禁用方法安全检查开关
        People p2 = (People) cons.newInstance("lele",18);
        System.out.println(p2); // people{name='lele', age=18}

        // 5、调用私有的属性
        Field nameField = c.getDeclaredField("name");
        nameField.setAccessible(true);
        nameField.set(p2,"mm");
        System.out.println(nameField.get(p2)); // mm

        // 6、调用私有的方法
        Method showNationMethod = c.getDeclaredMethod("showNation", String.class);
        showNationMethod.setAccessible(true);
        String info = (String) showNationMethod.invoke(p2,"CHN");
        System.out.println(info); // 我的国籍是：CHN
    }
}

class People{
    private String name;
    public int age;

    public People() {
        System.out.println("无参构造");
    }

    public People(int age){
        this.age = age;
    }

    private People(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void show(){
        System.out.println("公共的show方法");
    }

    private String showNation(String nation){
        return "我的国籍是：" + nation;
    }

    @Override
    public String toString() {
        return "people{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}